/*
    rejeane - random wallpaper setter
    Copyright (C) 2008 David Valentim Dias [dvdscripter@gmail.com]

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <windows.h>
#include "FreeImage.h"
#include <sys/time.h>
#include <sys/stat.h>
#include <winreg.h>

void *
Malloc (const size_t size)
{
    void *x = NULL;
    x = malloc (size);
    if ( !x )
    {
        MessageBox(NULL, "Running out of Memory", "Rejeane", MB_OK);
        exit (1);
    }
    return x;
}

/*
    func (modified) from FreeImage 3.11.0 documentation
*/

int
GenericLoader (const char* lpszPathName)
{
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
    FIBITMAP *dib;
    fif = FreeImage_GetFileType (lpszPathName, 0);
    FILE *fpin, *fpout;
    char buff [BUFSIZ];
    size_t len = 0;
    if ( fif == FIF_BMP )
    {
        if ( !(fpin = fopen (lpszPathName, "rb")) || !(fpout = fopen ("randomwall.bmp", "wb")) )
        {
            MessageBox(NULL, "Cannot open/create the image file.", "Rejeane", MB_OK);
            exit (1);
        }
        while ( !feof(fpin) ) 
        {
            len = fread (buff, sizeof (char), BUFSIZ, fpin);
            if (len > 0)
                fwrite (buff, sizeof (char), len, fpout);
        }
        fclose (fpin);
        fclose (fpout);
        return 1;
    }
        
    if (fif == FIF_UNKNOWN) 
        fif = FreeImage_GetFIFFromFilename (lpszPathName);
    if ( (fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading (fif) ) 
    {
        dib = FreeImage_Load (fif, lpszPathName, 0);
        FreeImage_Save (FIF_BMP, dib, "randomwall.bmp", 0);
        FreeImage_Unload (dib);
        return 1;
    }
    return 0;
}

typedef struct nodeT {
    char *data;
    unsigned int n;
    struct nodeT *next;
} node;

node *top=NULL;
node *PATHS=NULL;

void
add (const char *data) 
{
    node *new;
    new = Malloc (sizeof (node));
    if (!PATHS)
    {
        top = new;
        new->n = 1;
        new->next = NULL;
    }
    else
    {
        new->n = PATHS->n + 1;
        PATHS->next = new;
    }
    new->data = strdup (data);
    PATHS = new;
}

node*
get (const unsigned int x)
{
    node *n;
    unsigned a;
    for (n = top, a = 1; n && a != x; n = n->next, a++);
    return n;
}

int 
knownformat (const char *lpszPathName)
{
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
    fif = FreeImage_GetFileType (lpszPathName, 0);
    if (fif == FIF_UNKNOWN) 
    {
        fif = FreeImage_GetFIFFromFilename (lpszPathName);
    }   
    if ( (fif == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (fif) ) 
        return 0;
    else 
        return 1;
}

void 
dirs (const char *path)
{
    DIR *dir;
    char tmp [MAX_PATH];
    struct dirent *dir_info;
    struct stat finfo;
    dir = opendir (path);
    while ( (dir_info = readdir (dir)) )
	{
        if ( !strcmp(dir_info->d_name,".") || !strcmp(dir_info->d_name,"..") )
            continue;
        stat (path, &finfo);
        sprintf (tmp, "%s\\%s", path, dir_info->d_name);
        if ( knownformat (tmp) )
            add (tmp);
    }
    rewinddir (dir);
    while ( (dir_info = readdir (dir)) )
	{
        if ( !strcmp (dir_info->d_name, ".") || !strcmp (dir_info->d_name, "..") )
            continue;
        sprintf (tmp, "%s\\%s", path, dir_info->d_name);
        stat (tmp, &finfo);
        if ( S_ISDIR (finfo.st_mode) )
            dirs (tmp);
    }
    closedir (dir);
}

int
main (int argc, char *argv [])
{
    char path [MAX_PATH], cpath[MAX_PATH];
    node *random;
    HKEY key;
    if (argc > 1)
        sprintf (path, "%.*s", MAX_PATH, argv [1]);
	else if (argc == 1)
        getcwd (path, MAX_PATH);
    getcwd (cpath, MAX_PATH);
    dirs (path);
    if (!PATHS)
       exit (1);
    srand (time (0));
    snprintf (cpath, MAX_PATH, "%s\\randomwall.bmp", cpath);
    cpath [MAX_PATH] = 0;
    do {
        random = get (1 + rand () % PATHS->n);
    } while ( !GenericLoader (random->data) && strcmp(path, random->data) );
    if (RegOpenKeyEx (HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_SET_VALUE, &key) != ERROR_SUCCESS) 
        exit(1);
    if ( RegSetValueEx (key, "Wallpaper", 0, REG_SZ, cpath, strlen(cpath) + 1) != ERROR_SUCCESS )
        exit (1);
    RegCloseKey (key);
    SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, cpath, SPIF_SENDWININICHANGE);
    return 0;
}
